package Tests;

import static org.junit.Assert.*;

import java.rmi.RemoteException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import Controllers.BoardController;
import Controllers.PawnController;
import Models.BoardModel2D;
import Models.ChessPieceModel;
import Models.StandardBoardModel2D;

import Models.StandardChessPieceModel;
import Models.StandardPoint2D;

public class BoardControllerTest {
	
	private BoardController boardController;
	private BoardModel2D board;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
		board = new StandardBoardModel2D();
		boardController = new BoardController();
		boardController.resetStartingPotition(board);
		
	}

	@Test
	public void testMovePieceSimple() throws RemoteException {
		
		StandardPoint2D startPosition = new StandardPoint2D(0,1);
		StandardPoint2D endPosition = new StandardPoint2D(0,2);
		
		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(boardController.movePiece(startPosition, endPosition, board));
		
		Assert.assertNull(board.getPiece(startPosition));
		Assert.assertTrue(board.getPiece(endPosition) instanceof StandardChessPieceModel);
	}

	@Test
	public void testCantMoveNonExcisitingPiece() throws RemoteException {
		StandardPoint2D position = new StandardPoint2D(0,2);
		
		Assert.assertNull(board.getPiece(position));
		
		Assert.assertTrue(!boardController.movePiece(position, position, board));
		
		Assert.assertNull(board.getPiece(position));
	}

	@Test
	public void testMoveIllegalMove() throws RemoteException {

		StandardPoint2D position = new StandardPoint2D(0,1);
		
		Assert.assertTrue(board.getPiece(position) instanceof StandardChessPieceModel);
		
		Assert.assertTrue(!boardController.movePiece(position, position, board));
		
		Assert.assertTrue(board.getPiece(position) instanceof StandardChessPieceModel);
	}

	@Test
	public void testMoveCantJump1() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(2,0);
		StandardPoint2D blockingPotition = new StandardPoint2D(1,1);
		StandardPoint2D endPosition = new StandardPoint2D(0,2);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(!boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
	}

	@Test
	public void testMoveCantJump2() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(2,0);
		StandardPoint2D blockingPotition = new StandardPoint2D(3,1);
		StandardPoint2D endPosition = new StandardPoint2D(4,2);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(!boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
	}

	@Test
	public void testMoveCantJump3() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(2,7);
		StandardPoint2D blockingPotition = new StandardPoint2D(1,6);
		StandardPoint2D endPosition = new StandardPoint2D(0,5);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(!boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
	}

	@Test
	public void testMoveCantJump4() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(2,7);
		StandardPoint2D blockingPotition = new StandardPoint2D(3,6);
		StandardPoint2D endPosition = new StandardPoint2D(4,5);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(!boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
	}

	@Test
	public void testMoveCantJump5() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(0,0);
		StandardPoint2D blockingPotition = new StandardPoint2D(0,1);
		StandardPoint2D endPosition = new StandardPoint2D(0,5);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(!boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
	}

	@Test
	public void testMoveCanJump() throws RemoteException {

		StandardPoint2D startPosition = new StandardPoint2D(1,0);
		StandardPoint2D blockingPotition1 = new StandardPoint2D(1,1);
		StandardPoint2D blockingPotition2 = new StandardPoint2D(2,1);
		StandardPoint2D endPosition = new StandardPoint2D(2,2);

		Assert.assertTrue(board.getPiece(startPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition1) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition2) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(endPosition));
		
		Assert.assertTrue(boardController.movePiece(startPosition, endPosition, board));

		Assert.assertTrue(board.getPiece(endPosition) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition1) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition2) instanceof StandardChessPieceModel);
		Assert.assertNull(board.getPiece(startPosition));
	}

	@Test
	public void testMoveCanTake() throws RemoteException {

		StandardPoint2D blockingPotition2start = new StandardPoint2D(1,1); //White pawn
		StandardPoint2D blockingPotition2end = new StandardPoint2D(1,2);
		StandardPoint2D blockingPotition1start = new StandardPoint2D(4,6); //Black pawn
		StandardPoint2D blockingPotition1end = new StandardPoint2D(4,5);
		StandardPoint2D startPosition1 = new StandardPoint2D(2,0); //White bishop
		StandardPoint2D endPosition1 = new StandardPoint2D(0,2);
		StandardPoint2D startPosition2 = new StandardPoint2D(5,7); //Black bisop
		StandardPoint2D endPosition2 = new StandardPoint2D(0,2);
		
		Assert.assertTrue(board.getPiece(blockingPotition1start) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(blockingPotition2start) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(startPosition1) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(startPosition2) instanceof StandardChessPieceModel);

		Assert.assertTrue(boardController.movePiece(blockingPotition1start, blockingPotition1end, board));
		Assert.assertTrue(boardController.movePiece(blockingPotition2start, blockingPotition2end, board));
		Assert.assertTrue(boardController.movePiece(startPosition1, endPosition1, board));
		Assert.assertTrue(boardController.movePiece(startPosition2, endPosition2, board));
	}

	@Test
	public void testMoveCantTake() throws RemoteException {
		StandardPoint2D startPosition1 = new StandardPoint2D(2,0); //White bishop
		StandardPoint2D endPosition1 = new StandardPoint2D(1,1);
		StandardPoint2D blockingPotition2start = new StandardPoint2D(1,1); //White pawn
		
		Assert.assertTrue(board.getPiece(blockingPotition2start) instanceof StandardChessPieceModel);
		Assert.assertTrue(board.getPiece(startPosition1) instanceof StandardChessPieceModel);
		
		Assert.assertFalse(boardController.movePiece(startPosition1, endPosition1, board));
	}
	

}
